package com.pic.mgt.action;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Date;

import org.springframework.dao.DataAccessException;

import com.pic.mgt.dao.BasicBusinessTargetActionInfoBean;
import com.pic.mgt.dao.IBusinessTargetActionDao;
import com.pic.mgt.file.io.FileOperation;
import com.pic.mgt.log.IgxLog;
import com.pic.mgt.utils.IgxFileUtils;

// (送多方修改)
public abstract class MessageRecoverActionImpl implements MessageRecoverAction {
	protected String messageConfirmationFilenameSuffix;
	protected FileOperation fileOperation;
	protected IBusinessTargetActionDao businessTargetActionDao;
	
	protected boolean checkAndDoRecoverAction(File transactionFile,
											  File confirmationFileForTxFile,
											  File confirmationFileForMsgFile) {
		if (!transactionFile.exists() ||
			!confirmationFileForTxFile.exists() ||
			!confirmationFileForMsgFile.exists()) {
			/*
			 * 三個檔案有任一檔案不存在，表示已經有完成更新交易時間的動作，
			 * 因此直接將檔案全數刪除。
			 */

			boolean removeSuccessful =
				removeMessageRelatedFiles(transactionFile, confirmationFileForTxFile, confirmationFileForMsgFile);
			if (!removeSuccessful) {
				return false;
			}
		}
		else {
			/*
			 *  三個檔案都存在的情況下，要先去檢查是否完成更新交易時間的動作
			 *  (business target action 的 table)。若沒有，則直接 redetect trans ok 檔；
			 *  若有則直接將檔案全數刪除即可。 
			 */

			Date transactionFileTimeInfo[] = null;
			try {
				// throws DataAccessException
				transactionFileTimeInfo =
					getTransactionFileTimeInfo(transactionFile);
			} catch (DataAccessException e) {
				// ********************** Log **********************
				IgxLog.messageDetailsLog.error(this, e.getMessage());
				// ********************** Log **********************

				// ********************** Log **********************
				IgxLog.messageLog.error(this,
						"SUDA-201 Recovering message '{}' preprocess occured a database operation error",
						transactionFile.getName());
				// ********************** Log **********************
				return false;
			}

			if (null == transactionFileTimeInfo) {
				// ********************** Log **********************
				IgxLog.messageLog.error(this,
						"SUDA-202 Recovering message '{}' preprocess failed. Can't find transaction file record in database.",
						transactionFile.getName());
				// ********************** Log **********************
				return false;
			}

			/*
			 *  判斷如果交易時間為 null, 或 交易時間小於creating time，表示還沒完成更新交易時間的動作
			 *  ,必須 redetect file。否則直接將檔案全數刪除。
			 */
			Date lastTransctionTime = transactionFileTimeInfo[1];
			Date creatingTime = transactionFileTimeInfo[0];
			if (null == lastTransctionTime || 
					creatingTime.after(lastTransctionTime)) {
				boolean isRedetectFileSuccessful =
					redetectFile(transactionFile, confirmationFileForMsgFile);
				if (!isRedetectFileSuccessful) {
					return false;
				}
			}
			else {
				boolean removeSuccessful =
					removeMessageRelatedFiles(transactionFile, confirmationFileForTxFile, confirmationFileForMsgFile);
				if (!removeSuccessful) {
					return false;
				}
			}
		}
		
		return true;
	}
	
	/**
	 * 根據給定的 transaction file name，找出該 transaction file 於資料庫中的 creating time 
	 * 和 transaction time。
	 * @param transactionFilename
	 * @return Date 陣列。date[0]: creating time  date[1]: transaction time；若回傳為 null
	 * 表示該 transaction file 在資料庫中找不到記錄。
	 */
	protected Date[] getTransactionFileTimeInfo(File transactionFile) throws DataAccessException {
		BasicBusinessTargetActionInfoBean basicBusinessTargetActionInfoBean = null;
		
		basicBusinessTargetActionInfoBean = this.businessTargetActionDao.
						findBasicBusinessTargetActionInfoByFileName(transactionFile.getName());
		
		if (null == basicBusinessTargetActionInfoBean) {
			return null;
		}
		else {
			return new Date[] {basicBusinessTargetActionInfoBean.getCreatingTime(),
							   basicBusinessTargetActionInfoBean.getLastTransactionTime()};
		}
	}
	
	/**
	 * 
	 * @param transactionFile
	 * @param confirmationFileForTxFile
	 * @param confirmationFileForMsgFile
	 * @return true 表完完成移除；false 表示移除發生錯誤
	 */
	protected boolean removeMessageRelatedFiles(File transactionFile,
										   File confirmationFileForTxFile,
										   File confirmationFileForMsgFile) {
		// 移除交易檔
		try {
			this.fileOperation.deleteFile(transactionFile);
		} catch (FileNotFoundException e1) {
			// 不理會
		} catch (IOException e) {
			// ********************** Log **********************
			IgxLog.messageDetailsLog.error(this, e.getMessage());
			// ********************** Log **********************
			
			// ********************** Log **********************
			IgxLog.messageLog.error(this,
					"SUDA-203 Recovering message '{}' preprocess occured an I/O error in removeing file '{}'.",
					transactionFile.getName(), transactionFile.getAbsolutePath());
			// ********************** Log **********************
			
			return false;
		}
		
		// 移除交易檔的確認檔
		try {
			this.fileOperation.deleteFile(confirmationFileForTxFile);
		} catch (FileNotFoundException e1) {
			// 不理會
		} catch (IOException e) {
			// ********************** Log **********************
			IgxLog.messageDetailsLog.error(this, e.getMessage());
			// ********************** Log **********************
			
			// ********************** Log **********************
			IgxLog.messageLog.error(this,
					"SUDA-203 Recovering message '{}' preprocess occured an I/O error in removeing file '{}'.",
					transactionFile.getName(), confirmationFileForTxFile.getAbsolutePath());
			// ********************** Log **********************
			
			return false;
		}
		
		// 移除訊息的確認檔
		try {
			this.fileOperation.deleteFile(confirmationFileForMsgFile);
		} catch (FileNotFoundException e1) {
			// 不理會
		} catch (IOException e) {
			// ********************** Log **********************
			IgxLog.messageDetailsLog.error(this, e.getMessage());
			// ********************** Log **********************
			
			// ********************** Log **********************
			IgxLog.messageLog.error(this,
					"SUDA-203 Recovering message '{}' preprocess occured an I/O error in removeing file '{}'.",
					transactionFile.getName(), confirmationFileForMsgFile.getAbsolutePath());
			// ********************** Log **********************
			
			return false;
		}
		
		return true;
	}
	
	protected boolean redetectFile(File transactionFile, File confirmationFileForMsgFile) {
		try {
			IgxFileUtils.redetectFile(confirmationFileForMsgFile);
		} catch (IOException e) {
			// ********************** Log **********************
			IgxLog.messageDetailsLog.error(this, e.getMessage());
			// ********************** Log **********************
			
			// ********************** Log **********************
			IgxLog.messageLog.error(this,
							"SUDA-204 Recovering message '{}' preprocess occured an I/O error in redetecting confirmation file '{}' step.",
							transactionFile.getName(),
							confirmationFileForMsgFile.getAbsolutePath());
			// ********************** Log **********************
			return false;
		}
		
		return true;
	}
	
	// --- getter and setter ---

	public void setMessageConfirmationFilenameSuffix(
			String messageConfirmationFilenameSuffix) {
		this.messageConfirmationFilenameSuffix = messageConfirmationFilenameSuffix;
	}

	public void setFileOperation(FileOperation fileOperation) {
		this.fileOperation = fileOperation;
	}

	public void setBusinessTargetActionDao(
			IBusinessTargetActionDao businessTargetActionDao) {
		this.businessTargetActionDao = businessTargetActionDao;
	}

}
